/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.playground.core.service;

import com.playground.core.entity.GameTitle;
import com.playground.core.entity.LoggedPlayer;
import com.playground.core.entity.Room;
import java.util.List;
import java.util.Observer;

/**
 * Manipulates everything related to the queue system.
 * 
 * @author Tiago Peres
 */
public interface QueueService {
    /**
     * Add the given players to the queue of the game represented by "gameTitle".
     * The room where the players were put in is the returned value.
     * 
     * @param players the players to queue
     * @param gameTitle the game the players want to queue for
     * @return the room the users were put in
     */
    Room addToQueue(List<LoggedPlayer> players, GameTitle gameTitle);
    
    /**
     * After a room becomes full the players in the queue are asked if they are
     * ready to play the game (RoomStatus.waitingForPlayersConfirmation). This
     * method has the objective of saying a Player "player" has confirmed the
     * game, that he/she is ready.
     * 
     * This method verifies if the room status is "waitingForPlayersConfirmation",
     * if it is, it sets the player status to ready and verifies the others 
     * players statuses, if every player in the room is "ready", set the room
     * status to ready.
     * 
     * If the room status is not "waitingForPlayersConfirmation" false is returned.
     * 
     * Note that a confirmation that the user won't play the game (not ready)
     * should be a call to "removeFromQueue(Player)".
     * 
     * @param player the player who became ready to play
     * @param room the room hosting the player
     * @return true if the game was successfull confirmed, false otherwise
     */
    boolean confirmGame(LoggedPlayer player, Room room);
    
    /**
     * Remove the given player, hosted in the given room, from the queue.
     * 
     * 1. If the room status is not "opened" or "waitingForPlayersConfirmation"
     * return false;
     * 2. Remove the player from the room;
     * 3. If the room status was "waitingForPlayersConfirmation" change it to
     * "refused".
     * 
     * ATTENTION: If the room is full, false will be returned to prevent an
     * inconsistence of data: imagine a room becomes full, a queue observer gets 
     * the iterator of full rooms (RoomService.getFullRoomsIterator()), before 
     * the observe changes the room status to  "waitingForPlayersConfirmation", 
     * removePlayerFromQueueIsCalled and the status is changed to "refused", then
     * the queue observer, thinking the room is full, will ask the users in queue
     * if they're ready and change the room status to "waitingForPlayersConfirmation".
     * Everyone confirms the game and the game starts with not enough players.
     * Denying to remove the user doesn't seem to be the best solution, but it 
     * works, since in the rare case it happens the user will be soon asked if he
     * is ready to play the game, to quit the queue he/she just has to say "no".
     * 
     * @param player the player to be removed from the queue
     * @param room  the room hosting the player
     * @return true if the player was successfully removed from the queue, false
     * otherwise
     */
    boolean removePlayerFromQueue(LoggedPlayer player, Room room);
    
    /**
     * Requeues a previously refused room. A requeue of room will always put the
     * room in the front of the queue.
     * 
     * A room is requeued just if it's status is "refused". After being requeued,
     * the room status is changed to "opened" and "true" is returned.
     * 
     * If the room status was not "refused", "false" is returned.
     * 
     * @param room the room to be requeued
     * @return true if the room was successfully requeued, "false" otherwise
     */
    boolean requeueRoom(Room room);
    
    /**
     * Makes the room wait for its players to say they're ready to play.
     * 
     * A room can wait for players confirmation just if it is full. If the
     * room status is not "full", false will be returned, otherwise the room
     * status become "waitingForPlayersConfirmation" and true is returned.
     * 
     * False is returned in case the room doesn't exist.
     * 
     * @param room the room to wait for players confirmation
     * @return true if the room is waiting for players confirmation, false if the
     * operation was not successfull
     */
    boolean waitForPlayersConfirmation(Room room);
    
    /**
     * Set the room status to "running" if every user in the room is "ready".
     * 
     * @param room the room where the game will start
     * @return true if the operation was successfull, false otherwise
     */
    boolean startGame(Room room);
    
    /**
     * Adds an observer that will be notified everytime an important queue
     * event occurs.
     * Monitored events:
     * <ul>
     * <li>A room becomes full</li>
     * <li>A room becomes ready</li>
     * @param o the observer to observe the queues
     */
    void addObserver(Observer o);
}
